﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace blackhouse.BlackApart.Data {
    public abstract class AdoReservationDataAccess : IReservationDataAccess {

        #region ICalendarDataAccess Members

        //public abstract int SaveReservation(int reservationId, int apartmentId, double price, double priceWithoutRabat, float rabat, int numberOfPeople, DateTime startDate, DateTime endDate);

        //public abstract bool RemoveReservation(int reservationId);

        //public int SaveReservation(int reservationId, int apartmentId, int numberOfPeople, DateTime startDate, DateTime endDate) {
        //    return this.SaveReservation(reservationId, apartmentId, 0, 0, 0, numberOfPeople, startDate, endDate);
        //}

        //public ReservationData[] GetReservations(int apartmentId, DateTime startDate, DateTime endDate) {
        //    return this.ReadReservations(this.GetReaderForReservations(apartmentId, startDate, endDate));
        //}

        public ClientData GetClient(int clientId) {
            return this.ReadClient(this.GetReaderForClient(clientId));
        }

        public ClientData GetClientByEmail(string email) {
            return this.ReadClient(this.GetReaderForClientByEmail(email));
        }

        public PaymentData GetPaymentType(int paymentTypeId, string language) {
            return this.ReadPayment(this.GetReaderForPaymentType(paymentTypeId, language));
        }

        public PaymentData[] GetWebPaymentTypes(string language) {
            return this.ReadPayments(this.GetReaderForWebPaymentTypes(language));
        }

        //public ReservationData[] GetReservationsByHeader(int reservationId) {
        //    return this.ReadReservations(this.GetReaderForReservations(reservationId));
        //}

        //public ReservationHeaderData GetReservationHeader(int reservationId, string language) {
        //    return this.ReadReservationHeader(this.GetReaderForReservationHeader(reservationId, language));
        //}

        //public ReservationHeaderData GetReservationHeader(string reservationNumber, string language) {
        //    return this.ReadReservationHeader(this.GetReaderForReservationHeader(reservationNumber, language));
        //}

        public Dictionary<DateTime, int> GetAvabilityOfApartmentType(int groupId, DateTime fromDay, DateTime toDay) {
            Dictionary<DateTime, int> data = new Dictionary<DateTime, int>();
            IDataReader reader = this.GetAvabilityOfApartmentTypeReader(groupId, fromDay, toDay);
            while (reader.Read()) {
                data.Add(Convert.ToDateTime(reader["Date"]), Convert.ToInt32(reader["Free"]));
            }
            reader.Close();
            return data;
        }

        public abstract int SaveClient(string eMail, string phoneNumber, string personTitle, string firstName, string lastName, string language, string userPrefferCurrency);

        //public abstract int SavePaymentType(int id, string key, bool waitForCash);

        //public abstract int AddReservationHeader(int clientId, double totalPrice, double totalPriceWithoutRabat, float rabat, bool vatInvoice, int paymentTypeId, string reservationTypeId);

        //public abstract bool JoinReservationHeader(int userReservationId, int apartmentReservationId);

        //public abstract void AddMailToSend(int reservationId);

        public abstract bool ChangeReservationStatus(int reservationId, string newStatusKey);

        #endregion

        #region Abstracts

        //protected abstract IDataReader GetReaderForReservations(int apartmentId, DateTime startDate, DateTime endDate);
        //protected abstract IDataReader GetReaderForReservations(int reservationId);
        //protected abstract IDataReader GetReaderForReservationHeader(int reservationId, string language);
        //protected abstract IDataReader GetReaderForReservationHeader(string reservationNumber, string language);
        protected abstract IDataReader GetReaderForClient(int clientId);
        protected abstract IDataReader GetReaderForClientByEmail(string email);
        protected abstract IDataReader GetReaderForPaymentType(int paymentTypeId, string language);
        protected abstract IDataReader GetReaderForWebPaymentTypes(string language);
        protected abstract IDataReader AddWebReservationAndGetInfo(DateTime arrivalDate, DateTime departureDate, double priceWithRabat, double price, float rabat);
        protected abstract IDataReader GetWebReservationReader(int reservationId, string language);
        protected abstract IDataReader GetWebReservationReader(Guid reservationGuid, string language);
        protected abstract IDataReader GetWebReservationReader(string reservationNumber, string language);
        protected abstract IDataReader GetWebReservationForInterviewerReader();
        protected abstract IDataReader GetApartmentsWebReservationReader(int reservationId);
        protected abstract IDataReader GetRabatsWebReservationReader(int reservationId, string language);
        public abstract int AddApartmentToReservation(int reservationId, int apartmentTypeId, int forPeoples);
        public abstract int AddRabatToReservation(int reservationId, string rabatKey, float rabatValue);
        public abstract void RollbackWebReservation(int reservationId);
        public abstract bool UpdateWebReservation(int reservationId, DateTime arrivalDate, DateTime departureDate, double finalPrice, double price, float Rabat, bool vatInvoice, string comments, int clientId, int paymentTypeId);
        protected abstract IDataReader GetAvabilityOfApartmentTypeReader(int groupId, DateTime fromDay, DateTime toDay);

        #endregion

        #region Methods

        public WebReservationData GetWebReservation(int reservationId, string language) {
            return this.ReadWebReservation(this.GetWebReservationReader(reservationId, language));
        }

        public WebReservationData GetWebReservation(Guid reservationGuid, string language) {
            return this.ReadWebReservation(this.GetWebReservationReader(reservationGuid, language));
        }

        public WebReservationData GetWebReservation(string reservationNumber, string language) {
            return this.ReadWebReservation(this.GetWebReservationReader(reservationNumber, language));
        }

        public WebReservationData[] FindReservationForInterviewer() {
            return this.ReadWebReservations(this.GetWebReservationForInterviewerReader());
        }

        public ApartmentWebReservationData[] GetApartmentsWebReservation(int reservationId) {
            return this.ReadApartmentsWebReservationData(this.GetApartmentsWebReservationReader(reservationId));
        }

        public ReservationPriceRabatData[] GetRabatsWebReservation(int reservationId, string language) {
            return this.ReadReservationPriceRabats(this.GetRabatsWebReservationReader(reservationId, language));
        }

        public WebReservationSaveData AddWebReservation(DateTime arrivalDate, DateTime departureDate, double priceWithRabat, double price, float rabat) {
            return this.ReadReservationSaveData(this.AddWebReservationAndGetInfo(arrivalDate, departureDate, priceWithRabat, price, rabat));
        }

        private ReservationPriceRabatData[] ReadReservationPriceRabats(IDataReader reader) {
            List<ReservationPriceRabatData> data = new List<ReservationPriceRabatData>();
            while (reader.Read())
                data.Add(this.ReadReservationPriceRabatFields(reader));
            reader.Close();
            return data.ToArray();
        }

        private ReservationPriceRabatData ReadReservationPriceRabatFields(IDataReader reader) {
            ReservationPriceRabatData data = new ReservationPriceRabatData();
            data.RabatKey = Convert.ToString(reader["RabatKey"]);
            data.RabatName = Convert.ToString(reader["RabatName"]);
            data.RabatValue = Convert.ToSingle(reader["RabatValue"]);
            data.RecordId = Convert.ToInt32(reader["RecordId"]);
            data.OverrideRabatValue = Convert.ToSingle(reader["OverrideRabatValue"]);
            return data;
        }

        private ApartmentWebReservationData[] ReadApartmentsWebReservationData(IDataReader reader) {
            List<ApartmentWebReservationData> data = new List<ApartmentWebReservationData>();
            while (reader.Read()) {
                data.Add(this.ReadApartmentWebReservationDataFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private ApartmentWebReservationData ReadApartmentWebReservationDataFields(IDataReader reader) {
            ApartmentWebReservationData data = new ApartmentWebReservationData();
            data.ApartmentId = Convert.ToInt32(reader["ApartmentId"]);
            data.PeopleCount = Convert.ToInt32(reader["PeopleCount"]);
            data.RecordId = Convert.ToInt32(reader["RecordId"]);
            data.Price = Convert.ToDouble(reader["Price"]);
            return data;
        }

        private WebReservationData[] ReadWebReservations(IDataReader reader) {
            List<WebReservationData> data = new List<WebReservationData>();
            while (reader.Read())
                data.Add(this.ReadWebReservationFields(reader));
            reader.Close();
            return data.ToArray();
        }

        private WebReservationData ReadWebReservation(IDataReader reader) {
            WebReservationData data = default(WebReservationData);
            if (reader.Read())
                data = this.ReadWebReservationFields(reader);
            reader.Close();
            return data;
        }

        private WebReservationData ReadWebReservationFields(IDataReader reader) {
            WebReservationData data = new WebReservationData();
            data.ArrivalDate = Convert.ToDateTime(reader["ArrivalDate"]);
            data.DepartureDate = Convert.ToDateTime(reader["DepartureDate"]);
            data.Guid = (Guid)reader["Guid"];
            data.MainStatusId = Convert.ToInt32(reader["MainStatusId"]);
            data.Price = Convert.ToDouble(reader["Price"]);
            data.ReservationId = Convert.ToInt32(reader["ReservationId"]);
            data.ReservationNumber = Convert.ToString(reader["ReservationNumber"]);
            data.StatusDescription = Convert.ToString(reader["StatusDescription"]);
            data.StatusId = Convert.ToInt32(reader["StatusId"]);
            data.StatusName = Convert.ToString(reader["StatusName"]);
            data.StatusKey = Convert.ToString(reader["StatusKey"]);
            data.VatInvoice = Convert.ToBoolean(reader["VatInvoice"]);
            data.Comments = Convert.ToString(reader["Comments"]);
            data.OfficeComments = Convert.ToString(reader["OfficeComments"]);
            data.ClientId = Convert.ToInt32(reader["ClientId"]);
            data.PaymentTypeId = Convert.ToInt32(reader["PaymentTypeId"]);
            return data;
        }

        private WebReservationSaveData ReadReservationSaveData(IDataReader reader) {
            WebReservationSaveData data = default(WebReservationSaveData);
            if (reader.Read())
                data = this.ReadReservationSaveDataFields(reader);
            reader.Close();
            return data;
        }

        private WebReservationSaveData ReadReservationSaveDataFields(IDataReader reader) {
            WebReservationSaveData data = new WebReservationSaveData();
            data.Added = true;
            data.Guid = (Guid)reader["Guid"];
            data.ReservationId = Convert.ToInt32(reader["ReservationId"]);
            data.ReservationNumber = Convert.ToString(reader["ReservationNumber"]);
            return data;
        }

        //private ReservationData[] ReadReservations(IDataReader reader) {
        //    List<ReservationData> reservations = new List<ReservationData>();
        //    while (reader.Read()) {
        //        reservations.Add(this.ReadReservationFields(reader));
        //    }
        //    reader.Close();
        //    reader.Dispose();
        //    return reservations.ToArray();
        //}

        //private ReservationData ReadReservationFields(IDataReader reader) {
        //    ReservationData data = new ReservationData();
        //    data.Id = Convert.ToInt32(reader["Id"]);
        //    data.StartDate = Convert.ToDateTime(reader["StartDate"]);
        //    data.EndDate = Convert.ToDateTime(reader["EndDate"]);
        //    data.NumberOfPeople = Convert.ToInt32(reader["NumberOfPeople"]);
        //    data.ApartmentId = Convert.ToInt32(reader["ApartmentId"]);
        //    return data;
        //}

        private ClientData ReadClient(IDataReader reader) {
            ClientData data;
            if (reader.Read())
                data = this.ReadClientFields(reader);
            else
                data = default(ClientData);
            reader.Close();
            reader.Dispose();
            return data;
        }

        private ClientData ReadClientFields(IDataReader reader) {
            ClientData data = new ClientData();
            data.Id = Convert.ToInt32(reader["ClientId"]);
            data.EMail = Convert.ToString(reader["EMail"]);
            data.FirstName = Convert.ToString(reader["FirstName"]);
            data.LastName = Convert.ToString(reader["LastName"]);
            data.PersonTitle = Convert.ToString(reader["PersonTitle"]);
            data.PhoneNumber = Convert.ToString(reader["PhoneNumber"]);
            data.Language = Convert.ToString(reader["Language"]);
            data.PrefferCurrency = Convert.ToString(reader["Currency"]);
            return data;
        }

        private PaymentData[] ReadPayments(IDataReader reader) {
            List<PaymentData> data = new List<PaymentData>();
            while (reader.Read())
                data.Add(this.ReadPaymentFields(reader));
            reader.Close();
            reader.Dispose();
            return data.ToArray();
        }

        private PaymentData ReadPayment(IDataReader reader) {
            PaymentData data;
            if (reader.Read())
                data = this.ReadPaymentFields(reader);
            else
                data = default(PaymentData);
            reader.Close();
            reader.Dispose();
            return data;
        }

        private PaymentData ReadPaymentFields(IDataReader reader) {
            PaymentData data = new PaymentData();
            data.Key = Convert.ToString(reader["Key"]);
            data.PaymentTypeId = Convert.ToInt32(reader["Id"]);
            data.WaitForCash = Convert.ToBoolean(reader["WaitForCash"]);
            data.Name = Convert.ToString(reader["Display"]);
            data.Description = Convert.ToString(reader["Description"]);
            data.ExtraRabat = Convert.ToDouble(reader["ExtraRabat"]);
            return data;
        }

        //private ReservationHeaderData ReadReservationHeader(IDataReader reader) {
        //    ReservationHeaderData data;
        //    if (reader.Read())
        //        data = this.ReadReservationHeaderFields(reader);
        //    else
        //        data = default(ReservationHeaderData);
        //    reader.Close();
        //    reader.Dispose();
        //    return data;
        //}

        //[Obsolete]
        //private ReservationHeaderData ReadReservationHeaderFields(IDataReader reader) {
        //    ReservationHeaderData data = new ReservationHeaderData();
        //    data.Id = Convert.ToInt32(reader["ReservationId"]);
        //    data.Number = Convert.ToString(reader["Number"]);
        //    data.ArrivalDate = Convert.ToDateTime(reader["ArrivalDate"]);
        //    data.ClientId = Convert.ToInt32(reader["ClientId"]);
        //    data.DepartureDate = Convert.ToDateTime(reader["DepartureDate"]);
        //    data.PaymentType = Convert.ToInt32(reader["PaymentType"]);
        //    data.TotalPrice = Convert.ToDouble(reader["TotalPrice"]);
        //    data.TotalPriceWithoutRabat = Convert.ToDouble(reader["TotalPriceWithoutRabat"]);
        //    data.Rabat = Convert.ToSingle(reader["Rabat"]);
        //    data.VatInvoice = Convert.ToBoolean(reader["VatInvoice"]);
        //    data.StatusId = Convert.ToInt32(reader["StatusId"]);
        //    data.MainStatusId = Convert.ToInt32(reader["MainStatusId"]);
        //    data.StatusName = Convert.ToString(reader["Status"]);
        //    data.StatusDescription = Convert.ToString(reader["StatusDescription"]);
        //    data.StatusKey = Convert.ToString(reader["StatusKey"]);
        //    data.Guid = Convert.ToString(reader["Guid"]);
        //    return data;
        //}

        #endregion

    }
}
